package cn.kmsoft.jssc.controller;


import cn.kmsoft.common.DebugMsgInfo;
import cn.kmsoft.common.ResInfo;
import cn.kmsoft.common.ResultEnum;
import cn.kmsoft.common.utils.FileUtil;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.jssc.service.impl.DlhyServiceImpl;
import cn.kmsoft.jssc.service.impl.JsscServiceImpl;
import cn.kmsoft.stgeometry.util.Shp2Txt;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author jiao xn
 * @date 2023/2/2 15:39
 * @description ZIP Controller
 */
@Slf4j
@RestController
@Component
@Api(description = "技术审查", tags = "2-JsscController")
@RequestMapping("/jssc")
public class JsscController extends BaseController{
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss-SSS");

    //private static final Log logger = LogFactory.getLog(DlhyController.class);
    private final JsscServiceImpl jsscService;

    private final DlhyServiceImpl dlhyService;

    @Autowired
    public JsscController(JsscServiceImpl jsscService, DlhyServiceImpl dlhyService) {
        this.jsscService = jsscService;
        this.dlhyService = dlhyService;
    }

    @PostMapping(value = "", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "步骤1，上传 ZIP数据文件")
    public ResInfo uploadZipFile(@RequestParam("zipFile") MultipartFile zipFile)  {
        ResInfo resInfo = new ResInfo();

        Date startDate= new Date();
        String startDateStr= sdf.format(startDate);
        System.out.println();
        System.out.println("*******************************************");
        String startMsg=String.format("--->步骤1，uploadZipFile started, 上传ZIP数据文件开始， startTime: %s",startDateStr);
        log.info(startMsg);

        //校验zip后缀
        this.validateZipFileSuffix(zipFile);
        Map<String, String> maps = new HashMap<>();

        try {
            String zipFilenameInServer = jsscService.saveToServer(zipFile);

            String endMsg = String.format("--->步骤1，uploadZipFile finished, 上传ZIP数据文件成果,返回projectId: %s",zipFilenameInServer);
            //System.out.println(endMsg);
            log.info(endMsg);

            //数据所在的路径
            maps.put("zipFilename", zipFilenameInServer);

            resInfo.setCode(ResultEnum.SUCCESS.getCode());
            resInfo.setData(maps);
            resInfo.setStatus(ResInfo.SUCCESS);
            resInfo.setMsg(endMsg);
        }catch (IOException ex){
            String errorMsg = String.format("--->步骤1，uploadZipFile failed, detaimMsg: %s" ,ex.getMessage());
            //System.out.println(errorMsg);
            log.error(errorMsg);

            maps.put("zipFilename", null);
            resInfo.setStatus(ResInfo.FAIL);
            resInfo.setData(maps);
            resInfo.setCode(ResultEnum.BUSINESS_FAILED.getCode());
            resInfo.setMsg(errorMsg);
        }

        return resInfo;
    }

    @GetMapping(value = "/{zipFilename}/shapefiles")
    @ApiOperation(value = "步骤2，解压上传的zip包，获取 Shapefile 文件列表")
    public ResInfo getZipContentInfo( @PathVariable String zipFilename) throws IOException {
        String msg = String.format("--->步骤2，getZipContentInfo started, 解压上传的zip包，获取 Shapefile 文件列表, projectId: %s",zipFilename);
        //System.out.println(msg);
        log.info(msg);

        Map<String, String> results = this.jsscService.getContent(zipFilename);
        return  ResInfo.success(msg,results);
    }

    @GetMapping(value = "/{zipFilename}/shapefiles/{shapefileName}/path")
    @ApiOperation(value= "步骤2-1，获取指定 Shapefile 文件的 绝对路径")
    public ResInfo getShapefilePath(@PathVariable String zipFilename,
                                   @PathVariable String shapefileName) {
        ResInfo resInfo = null;
        String msg=String.format("--->步骤2-1，getShapefilePath stared, 获取指定 Shapefile 文件的 绝对路径, projectId: %s，shpName: %s",zipFilename,shapefileName);
        //System.out.println(msg);
        log.info(msg);

        String shppath = this.jsscService.getShapefilePath(zipFilename, shapefileName);
        if( !StringUtil.isNullOrEmpty(shppath)) {
            resInfo = ResInfo.success("getShapefilePath success", shppath);
        }else {
            resInfo = ResInfo.failed("getShapefilePath failed");
        }

        return resInfo;
    }

    @GetMapping(value = "/{zipFilename}/check-result")
    @ApiOperation(value = "步骤3，开展压缩包内的shape文件格式检查，检查结果输出到txt文件中")
    public ResInfo checkZipContentInfo(@PathVariable String zipFilename) throws IOException {

        String startMsgStr = String.format("--->步骤3，开展压缩包内的shape文件格式检查，jobId: %s ",zipFilename);
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        ResInfo resInfo = this.jsscService.checkZipContentInfo2(zipFilename);
        return resInfo;
    }

    @GetMapping(value = "/{zipFilename}/download-check-result")
    @ApiOperation(value = "步骤3-1，下载数据zip文件的检查结果为txt")
    public void downloadCheckResult(HttpServletResponse response,
                                    @PathVariable String zipFilename) throws IOException {
        String startMsgStr = String.format("--->步骤3-1，downloadCheckResult started, jobId: %s",zipFilename);
        System.out.println();
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        this.jsscService.downloadCheckResult(response, zipFilename);
    }

    @GetMapping(value = "/{zipFilename}/analysis-result")
    @ApiOperation(value = "步骤4-1，下载地类还原分析结果为zip压缩包")
    public void downloadAnalysisResult(HttpServletResponse httpServletResponse,
                                       @PathVariable String zipFilename) throws IOException {
        String startMsgStr = String.format("--->步骤4-1，downloadAnalysisResult startd，下载地类还原分析结果为zip压缩包,jobId: %s ",zipFilename);
        System.out.println(startMsgStr);
        log.info(startMsgStr);

        String newZipName = zipFilename+"_DlhyResult.zip";
        httpServletResponse.setContentType("application/zip");
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + newZipName );

        this.jsscService.newZipdownloadAnalysisResult(zipFilename, newZipName, httpServletResponse.getOutputStream());
    }

    @ApiOperation(value = "步骤4-2，下载用地红线范围TXT", notes = "用地红线范围转TXT坐标串")
    @GetMapping(value = "/{zipFilename}/download-redline-result")
    public void downloadRedlineResult(HttpServletResponse httpServletResponse,
                                 @PathVariable String zipFilename) {
        Date dateNow = new Date();

        //1-开始
        String msg=String.format("--->步骤4-2，downloadRedlineResult stared, 下载用地红线范围标准坐标串到ydhxfw.txt文件中, projectId: %s",zipFilename);
        //System.out.println(msg);
        log.info(msg);

        this.jsscService.downloadRedlineResult(httpServletResponse,zipFilename);

        String finishedStr = String.format("--->downloadRedlineResult finished! ,%s",zipFilename);
        //System.out.println(finishedStr);
        log.info(finishedStr);
    }

    @GetMapping(value = "/{zipFilename}/shapefiles/{shapefileName}")
    @ApiOperation(value = "获取指定 Shapefile文件的GeoJSON 数据")
    public ResInfo getShapefileAsGeoJSON(@PathVariable String zipFilename,
                                        @PathVariable String shapefileName) throws IOException {

        String startMsgStr = String.format("--->getShapefileAsGeoJSON startd，获取指定 Shapefile文件的GeoJSON 数据,jobId: %s ，shpName: %s",zipFilename,shapefileName);
        //System.out.println(startMsgStr);
        log.info(startMsgStr);

        Map<String, Object> results=this.jsscService.convertShapefileToGeoJSON(zipFilename, shapefileName);
        return ResInfo.success(startMsgStr, results);
    }

//    @GetMapping(value = "/{zipFilename}/shapefilesForResult/{shapefileName}")
//    @Operation(summary = "获取指定 Shapefile 文件的 GeoJSON 数据（用于地类还原的结果分析）")
//    public Object convertShapefileToGeoJSON(
//            @PathVariable
//                    String zipFilename,
//            @PathVariable
//                    String shapefileName
//    ) throws Exception {
//        return this.jsscService.convertShapefileToGeoJSONForDlhyResult(zipFilename, shapefileName);
//    }


    @GetMapping(value = "/{zipFilename}/check-excel")
    @ApiOperation(value = "步骤5，检查土地面积分类表并输出excel文件")
    public void checkExcel(HttpServletRequest request, HttpServletResponse response,
                           @PathVariable String zipFilename) throws IOException {
        String startMsgStr = String.format("--->步骤5，checkExcel started,检查土地面积分类表并输出excel文件,jobId: %s ",zipFilename);
        //System.out.println(startMsgStr);
        log.info(startMsgStr);

        /**
         * edit by zhoukj 20230803
         * 1、将上传的excel中不正确的值替换成，叠加分析出来的值。
         * 2、将水田、耕地、农用地总面积减少1%以上，建设用地和未利用地等面积增加1%以上；按百分比浮动比较；
         */
        //this.jsscService.checkExcel(request,response,zipFilename);
        //this.jsscService.checkExcelEx(request,response,zipFilename);
        this.jsscService.newCheckExcelEx2(request,response,zipFilename);
    }


    @ApiOperation(value = "获取技术审查处理状态", notes = "获取技术审查状态,包含：10001（权属界线融合已完成)，10003（地类还原分析已完成）")
    @RequestMapping(value = "/getJsscStatusByProjectId", method= RequestMethod.GET)
    public ResInfo getJsscStatusByProjectId(String projectId){
        ResInfo resInfo = new ResInfo();
        if( StringUtil.isNullOrEmpty(projectId) ){
            resInfo.setStatus(ResInfo.FAIL);
            resInfo.setCode(500);
            resInfo.setMsg("projectId不能为空");

            return resInfo;
        }
        ValueOperations ops= redisTemplate.opsForValue();
        Object obj = ops.get("jssc-"+projectId);
        String val= obj != null ? obj.toString(): "";

        String getJsscStatusMsg = String.format("--->getJsscStatusFromRedis,jssc-%s: %s",projectId,val);
        //System.out.println(getJsscStatusMsg);
        if( StringUtil.isNullOrEmpty(val)){
            resInfo.setCode(500);
            resInfo.setStatus(ResInfo.ERROR);
            //resInfo.setStatus(ResInfo.SUCCESS);
            resInfo.setRes(-1);
            resInfo.setMsg(String.format("--->该编号未完成技术审查运算，jobId: %s,状态码为空",projectId));
        }else {
            resInfo.setCode(200);
            resInfo.setStatus(ResInfo.SUCCESS);
            resInfo.setRes(val);
            resInfo.setMsg(String.format("--->获取技术审查状态码成功,jobId: %s, 状态码: %s", projectId, val ));
        }

        return resInfo;
    }



    private void validateZipFileSuffix(MultipartFile file) {
        String fileSuffix = FileUtil.getFileSuffix(file);
        if (!".zip".equals(fileSuffix)) {
            throw new InvalidParameterException("请选择ZIP文件");
        }
    }

}
